home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
archiver
/
unix
/
zip19p1.zoo
/
os2
/
os2zip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-26
|
21KB
|
922 lines
/*
* @(#)dir.c 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
* Ported to OS/2 by Kai Uwe Rommel
* December 1989, February 1990
* Change for HPFS support, October 1990
*/
/* does also contain EA access code for use in ZIP */
#ifdef __EMX__
#define __32BIT__
#endif
#include "zip.h"
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#ifdef __WATCOMC__
#include <malloc.h>
unsigned char __near _osmode = OS2_MODE;
#endif
#define INCL_NOPM
#define INCL_DOSNLS
#define INCL_DOSERRORS
#include <os2.h>
#include "os2zip.h"
#define EAID 0x0009
#ifdef __32BIT__
#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
DosFindFirst(p1, p2, p3, p4, p5, p6, 1)
#else
#define DosQueryCurrentDisk DosQCurDisk
#define DosQueryFSAttach(p1, p2, p3, p4, p5) \
DosQFSAttach(p1, p2, p3, p4, p5, 0)
#define DosQueryPathInfo(p1, p2, p3, p4) \
DosQPathInfo(p1, p2, p3, p4, 0)
#define DosSetPathInfo(p1, p2, p3, p4, p5) \
DosSetPathInfo(p1, p2, p3, p4, p5, 0)
#define DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7) \
DosEnumAttribute(p1, p2, p3, p4, p5, p6, p7, 0)
#define DosFindFirst(p1, p2, p3, p4, p5, p6) \
DosFindFirst(p1, p2, p3, p4, p5, p6, 0)
#define DosMapCase DosCaseMap
#endif
#ifndef UTIL
extern int noisy;
#ifndef S_IFMT
#define S_IFMT 0xF000
#endif
static int attributes = A_DIR | A_HIDDEN | A_SYSTEM;
static char *getdirent(char *);
static void free_dircontents(struct _dircontents *);
#ifdef __32BIT__
static HDIR hdir;
static ULONG count;
static FILEFINDBUF3 find;
#else
static HDIR hdir;
static USHORT count;
static FILEFINDBUF find;
#endif
DIR *opendir(char *name)
{
struct stat statb;
DIR *dirp;
char c;
char *s;
struct _dircontents *dp;
char nbuf[MAXPATHLEN + 1];
int len;
strcpy(nbuf, name);
len = strlen (nbuf);
s = nbuf + len;
if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
(strlen(nbuf) > 1) )
{
nbuf[strlen(nbuf) - 1] = 0;
if ( nbuf[strlen(nbuf) - 1] == ':' )
strcat(nbuf, "\\.");
}
else
if ( nbuf[strlen(nbuf) - 1] == ':' )
strcat(nbuf, ".");
if (stat(nbuf, &statb) < 0 || (statb.st_mode & S_IFMT) != S_IFDIR)
return NULL;
if ( (dirp = malloc(sizeof(DIR))) == NULL )
return NULL;
if ( nbuf[strlen(nbuf) - 1] == '.' )
strcpy(nbuf + strlen(nbuf) - 1, "*.*");
else
if ( ((c = nbuf[strlen(nbuf) - 1]) == '\\' || c == '/') &&
(strlen(nbuf) == 1) )
strcat(nbuf, "*.*");
else
strcat(nbuf, "\\*.*");
dirp -> dd_loc = 0;
dirp -> dd_contents = dirp -> dd_cp = NULL;
if ((s = getdirent(nbuf)) == NULL)
return dirp;
do
{
if (((dp = malloc(sizeof(struct _dircontents))) == NULL) ||
((dp -> _d_entry = malloc(strlen(s) + 1)) == NULL) )
{
if (dp)
free(dp);
free_dircontents(dirp -> dd_contents);
return NULL;
}
if (dirp -> dd_contents)
{
dirp -> dd_cp -> _d_next = dp;
dirp -> dd_cp = dirp -> dd_cp -> _d_next;
}
else
dirp -> dd_contents = dirp -> dd_cp = dp;
strcpy(dp -> _d_entry, s);
dp -> _d_next = NULL;
dp -> _d_size = find.cbFile;
dp -> _d_mode = find.attrFile;
dp -> _d_time = *(unsigned *) &(find.ftimeLastWrite);
dp -> _d_date = *(unsigned *) &(find.fdateLastWrite);
}
while ((s = getdirent(NULL)) != NULL);
dirp -> dd_cp = dirp -> dd_contents;
return dirp;
}
void closedir(DIR * dirp)
{
free_dircontents(dirp -> dd_contents);
free(dirp);
}
struct direct *readdir(DIR * dirp)
{
static struct direct dp;
if (dirp -> dd_cp == NULL)
return NULL;
dp.d_namlen = dp.d_reclen =
strlen(strcpy(dp.d_name, dirp -> dd_cp -> _d_entry));
dp.d_ino = 0;
dp.d_size = dirp -> dd_cp -> _d_size;
dp.d_mode = dirp -> dd_cp -> _d_mode;
dp.d_time = dirp -> dd_cp -> _d_time;
dp.d_date = dirp -> dd_cp -> _d_date;
dirp -> dd_cp = dirp -> dd_cp -> _d_next;
dirp -> dd_loc++;
return &dp;
}
void seekdir(DIR * dirp, long off)
{
long i = off;
struct _dircontents *dp;
if (off >= 0)
{
for (dp = dirp -> dd_contents; --i >= 0 && dp; dp = dp -> _d_next);
dirp -> dd_loc = off - (i + 1);
dirp -> dd_cp = dp;
}
}
long telldir(DIR * dirp)
{
return dirp -> dd_loc;
}
static void free_dircontents(struct _dircontents * dp)
{
struct _dircontents *odp;
while (dp)
{
if (dp -> _d_entry)
free(dp -> _d_entry);
dp = (odp = dp) -> _d_next;
free(odp);
}
}
static char *getdirent(char *dir)
{
int done;
static int lower;
if (dir != NULL)
{ /* get first entry */
hdir = HDIR_CREATE;
count = 1;
done = DosFindFirst(dir, &hdir, attributes, &find, sizeof(find), &count);
lower = IsFileSystemFAT(dir);
}
else /* get next entry */
done = DosFindNext(hdir, &find, sizeof(find), &count);
if (done == 0)
{
if ( lower )
StringLower(find.achName);
return find.achName;
}
else
{
DosFindClose(hdir);
return NULL;
}
}
/* FAT / HPFS detection */
int IsFileSystemFAT(char *dir)
{
static USHORT nLastDrive = -1, nResult;
ULONG lMap;
BYTE bData[64], bName[3];
#ifdef __32BIT__
ULONG nDrive, cbData;
PFSQBUFFER2 pData = (PFSQBUFFER2) bData;
#else
USHORT nDrive, cbData;
PFSQBUFFER pData = (PFSQBUFFER) bData;
#endif
if ( _osmode == DOS_MODE )
return TRUE;
else
{
/* We separate FAT and HPFS+other file systems here.
at the moment I consider other systems to be similar to HPFS,
i.e. support long file names and beeing case sensitive */
if ( isalpha(dir[0]) && (dir[1] == ':') )
nDrive = to_up(dir[0]) - '@';
else
DosQueryCurrentDisk(&nDrive, &lMap);
if ( nDrive == nLastDrive )
return nResult;
bName[0] = (char) (nDrive + '@');
bName[1] = ':';
bName[2] = 0;
nLastDrive = nDrive;
cbData = sizeof(bData);
if ( !DosQueryFSAttach(bName, 0, FSAIL_QUERYNAME, (PVOID) pData, &cbData) )
nResult = !strcmp(pData -> szFSDName + pData -> cbName, "FAT");
else
nResult = FALSE;
/* End of this ugly code */
return nResult;
}
}
/* access mode bits and time stamp */
int GetFileMode(char *name)
{
#ifdef __32BIT__
FILESTATUS3 fs;
return DosQueryPathInfo(name, 1, &fs, sizeof(fs)) ? -1 : fs.attrFile;
#else
USHORT mode;
return DosQFileMode(name, &mode, 0L) ? -1 : mode;
#endif
}
long GetFileTime(char *name)
{
#ifdef __32BIT__
FILESTATUS3 fs;
#else
FILESTATUS fs;
#endif
USHORT nDate, nTime;
if ( DosQueryPathInfo(name, 1, (PBYTE) &fs, sizeof(fs)) )
return -1;
nDate = * (USHORT *) &fs.fdateLastWrite;
nTime = * (USHORT *) &fs.ftimeLastWrite;
return ((ULONG) nDate) << 16 | nTime;
}
void SetFileTime(char *path, long stamp)
{
FILESTATUS fs;
USHORT fd, ft;
USHORT nLength;
char szName[CCHMAXPATH];
if ( DosQueryPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs)) )
return;
fd = (USHORT) (stamp >> 16);
ft = (USHORT) stamp;
fs.fdateLastWrite = fs.fdateCreation = * (FDATE *) &fd;
fs.ftimeLastWrite = fs.ftimeCreation = * (FTIME *) &ft;
DosSetPathInfo(path, FIL_STANDARD, (PBYTE) &fs, sizeof(fs), 0);
}
/* FAT / HPFS name conversion stuff */
int IsFileNameValid(char *name)
{
HFILE hf;
#ifdef __32BIT__
ULONG uAction;
#else
USHORT uAction;
#endif
switch( DosOpen(name, &hf, &uAction, 0, 0, FILE_OPEN,
OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE, 0) )
{
case ERROR_INVALID_NAME:
case ERROR_FILENAME_EXCED_RANGE:
return FALSE;
case NO_ERROR:
DosClose(hf);
default:
return TRUE;
}
}
void ChangeNameForFAT(char *name)
{